﻿//-----------------------------------------------------------------------
// <copyright file="Encryption.cs" company="Redmist">
//     Copyright (c) Damien T Smith. All rights reserved.
// </copyright>
// <author>Damien Smith</author>
//-----------------------------------------------------------------------

namespace Redmist.UsageMonitor.Controller
{
    using System;
    using System.IO;
    using System.Security.Cryptography;
    using System.Text;

    /// <summary>Encrypts and Decrypts strings using the Rijndael algorithm.</summary>
    public class Encryption
    {
        /// <summary>Encrypts a string.</summary>
        /// <param name="plainText">A System.String representing the string to be encrypted.</param>
        /// <returns>A System.String representing an encrypted string.</returns>
        public static string EncryptString(string plainText)
        {
            RijndaelManaged rijndaelCipher = new RijndaelManaged();
            rijndaelCipher.Key = CreateKey();
            rijndaelCipher.IV = CreateIV();
            string cipherText = string.Empty;
            using (MemoryStream memoryStream = new MemoryStream())
            {
                ICryptoTransform rijndaelEncryptor = rijndaelCipher.CreateEncryptor();
                using (CryptoStream cryptoStream = new CryptoStream(memoryStream, rijndaelEncryptor, CryptoStreamMode.Write))
                {
                    byte[] plainBytes = Encoding.ASCII.GetBytes(plainText);
                    cryptoStream.Write(plainBytes, 0, plainBytes.Length);
                    cryptoStream.FlushFinalBlock();
                    byte[] cipherBytes = memoryStream.ToArray();
                    cipherText = Convert.ToBase64String(cipherBytes, 0, cipherBytes.Length);
                }
            }

            return cipherText;
        }

        /// <summary>Decrypts a string.</summary>
        /// <param name="cipherText">A System.String representing the string to be decrypted.</param>
        /// <returns>A System.String representing the decrypted string.</returns>
        public static string DecryptString(string cipherText)
        {
            RijndaelManaged rijndaelCipher = new RijndaelManaged();
            rijndaelCipher.Key = CreateKey();
            rijndaelCipher.IV = CreateIV();
            string plainText = String.Empty;
            using (MemoryStream memoryStream = new MemoryStream())
            {
                ICryptoTransform rijndaelDecryptor = rijndaelCipher.CreateDecryptor();
                using (CryptoStream cryptoStream = new CryptoStream(memoryStream, rijndaelDecryptor, CryptoStreamMode.Write))
                {
                    byte[] cipherBytes = Convert.FromBase64String(cipherText);
                    cryptoStream.Write(cipherBytes, 0, cipherBytes.Length);
                    cryptoStream.FlushFinalBlock();
                    byte[] plainBytes = memoryStream.ToArray();
                    plainText = Encoding.ASCII.GetString(plainBytes, 0, plainBytes.Length);
                }
            }

            return plainText;
        }

        /// <summary>Creates a 256-bit encryption key.</summary>
        /// <returns>A byte array representing the encryption key.</returns>
        /// <remarks>Storing the key in this manner is NOT secure.  For most purposes this is adequate but like all client side encryption, it will not protect from reverse engineering.</remarks>
        private static byte[] CreateKey()
        {
            return new byte[] { 7, 22, 13, 4, 15, 11, 7, 12, 19, 1, 2, 19, 3, 8, 23, 5, 9, 13, 9, 12, 4, 6, 2, 22 };
        }

        /// <summary>Creates a 128-bit initialization vector.</summary>
        /// <returns>A byte array representing the initialization vector.</returns>
        private static byte[] CreateIV()
        {
            return new byte[] { 3, 2, 1, 2, 22, 13, 4, 15, 22, 13, 4, 15, 22, 13, 4, 15 };
        }
    }
}
